package net.pws.common.beanutils.converter;

import java.util.Properties;

import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.converters.AbstractArrayConverter;
import org.springframework.util.StringUtils;

public class PropertiesConverter extends AbstractArrayConverter {
    
    // ----------------------------------------------------------- Constructors
    
    /**
     * Create a {@link Converter} that will throw a {@link ConversionException}
     * if a conversion error occurs.
     */
    public PropertiesConverter() {
        
        this.defaultValue = null;
        this.useDefault = false;
        
    }
    
    /**
     * Create a {@link Converter} that will return the specified default value
     * if a conversion error occurs.
     * 
     * @param defaultValue
     *            The default value to be returned
     */
    public PropertiesConverter(Object defaultValue) {
        
        this.defaultValue = defaultValue;
        this.useDefault = true;
        
    }
    
    // --------------------------------------------------------- Public Methods
    
    /**
     * Convert the specified input object into an output object of the specified
     * type.
     * 
     * @param type
     *            Data type to which this value should be converted
     * @param value
     *            The input value to be converted
     * @exception ConversionException
     *                if conversion cannot be performed successfully
     */
    public Object convert(Class type, Object value) {
        // Deal with a null value
        if (value == null) {
            if (useDefault) {
                return (defaultValue);
            }
            else {
                throw new ConversionException("No value specified");
            }
        }
        
        if (value instanceof Properties) {
            return (value);
        }
        
        // Deal with input value as a String array
        if (strings.getClass() == value.getClass()) {
            try {
                return StringUtils.splitArrayElementsIntoProperties((String[]) value,
                                                                    "=");
            }
            catch (Exception e) {
                if (useDefault) {
                    return (defaultValue);
                }
                else {
                    throw new ConversionException(value.toString(), e);
                }
            }
        }
        
        // Parse the input value as a String into elements
        // and convert to the appropriate type
        try {
            return StringUtils.splitArrayElementsIntoProperties(commaDelimitedStringToStringArray(value.toString()),
                                                                "=");
        }
        catch (Exception e) {
            if (useDefault) {
                return (defaultValue);
            }
            else {
                throw new ConversionException(value.toString(), e);
            }
        }
        
    }
    
    private String[] commaDelimitedStringToStringArray(String svalue) {
        
        // Validate the passed argument
        if (svalue == null) {
            throw new NullPointerException();
        }
        
        // Trim any matching '{' and '}' delimiters
        svalue = svalue.trim();
        if (svalue.startsWith("{") && svalue.endsWith("}")) {
            svalue = svalue.substring(1, svalue.length() - 1);
        }
        
        return StringUtils.commaDelimitedListToStringArray(svalue);
    }
    
}
